package Utils;

import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.io.FileUtils;
import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import java.io.File;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

public class Tools {

    static Logger logger = LoggerFactory.getLogger(Tools.class);

    public static List<Map<String, String>> getDbDownloadInfo(MongoCollection collection){
        /**
         * 提取数据库中所有的信息
         */
        logger.info("开始读取数据库 " + collection.getNamespace().getCollectionName() + "······");
        FindIterable<Document> findIterable = collection.find();

        List<Map<String, String>> documents = new ArrayList<>();
        for (Document item : findIterable){
            Document document = new Document();
            String title = item.getString("title_name").replace("*", "").replace(":", "：").replace("\"", "").replace("</em>","").replace("<em>","").replace("<","（").replace(">","）");
            String url = "http://www.cninfo.com.cn/new/announcement/download?bulletinId=" + item.getString("_id") + "&announceTime=" + item.getString("announceTime");

            Map<String, String> data = new HashMap<>();
            data.put("title", title);
            data.put("url", url);

            documents.add(data);
        }

        logger.info("读取数据库完成!!!\n读取数据" + documents.size() + "条。" );
        return documents;
    }

    public static List<String> getAllFilePath(String base_file_path) {
        /**
         * 获取base_file_path 下所有文件的绝对地址
         */
        File BaseFile = new File(base_file_path);

        if (BaseFile.isFile() || !BaseFile.exists()) {
            throw new NullPointerException(base_file_path + " 该地址不是文件夹 或 该文件夹不存在， 请检查文件路径！");
        }

        File[] files = BaseFile.listFiles();
        List<String> list = new ArrayList<>();
        for (File file : files) {
            if (file.isDirectory())
                list.addAll(getAllFilePath(file.getAbsolutePath()));
            else
                list.add(file.getAbsolutePath());
        }

        return list;
    }

    public static void initFolder(String folderPath){
        /**
         * 检查folderPath是否存在
         * 若不存在，创建相关文件夹
         */
        File folder = new File(folderPath);

        if (!folder.exists() && !folder.isDirectory()) {
            folder.mkdirs();
            System.out.println("创建文件夹");
        } else {
            System.out.println("文件夹已存在");
        }
    }


    public static List<String> getDateList(String startDateStr, String endDateStr){
        /**
         * 解析startDate至endDate之间所有的日期，转换成str，组成list返回
         *
         */
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd");
        List<String> dateList = new ArrayList<>();
        try {
            Date startDate = simpleDateFormat1.parse(startDateStr);
            Date endDate = simpleDateFormat1.parse(endDateStr);
            Calendar calendar = Calendar.getInstance();
            for (Date i = startDate; endDate.compareTo(i) >= 0 ; i = calendar.getTime()) {
                dateList.add(simpleDateFormat1.format(i));
                calendar.setTime(i);
                calendar.add(Calendar.DAY_OF_MONTH, 1);
            }
        } catch (ParseException e) {
            e.printStackTrace();
            System.out.println("检查日期格式（yyyy-MM-dd）！");
            return null;
        }

        return dateList;
    }

    public static void Download(Map<String, String> dataMap, String savePath) throws InterruptedException {
        /**
         * dataMap有两个entity
         * “title”:文件名（文件名需包含文件类型）
         * "url":文件下载连接
         */
        logger.info("----------开始下载---"+ dataMap.get("title"));
        Request request = new Request.Builder()
                .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36")
                .addHeader("Referer", "http://www.cninfo.com.cn/new/fulltextSearch?notautosubmit=&keyWord=%E7%8B%AC%E8%91%A3%E6%84%8F%E8%A7%81")
                .addHeader("Host", "www.cninfo.com.cn")
                .addHeader("Connection", "keep-alive")
                .addHeader("X-Requested-With", "XMLHttpRequest")
                .url(dataMap.get("url"))
                .build();

        OkHttpClient client = new OkHttpClient()
                .newBuilder().connectTimeout(60, TimeUnit.SECONDS)
                .sslSocketFactory(createSSLSocketFactory(), new TrustAllCerts())
                .hostnameVerifier(new TrustAllHostnameVerifier())
                .readTimeout(60, TimeUnit.SECONDS).build();
        client.dispatcher().setMaxRequests(10);
        client.dispatcher().setMaxRequestsPerHost(5);

        Call call=client.newCall(request);
        Response response = null;
        try{
            response = call.execute();
            while (true){
                if(response!=null&&response.isSuccessful()) {
                    byte[] data = response.body().bytes();
                    FileUtils.writeByteArrayToFile(new File(savePath + dataMap.get("title")), data);
                    logger.info("----------已下载---"+dataMap.get("title"));
                }
                break;
            }
        }catch (Exception e){
            Thread.sleep(2*1000);
            e.printStackTrace();

        }

        Thread.sleep(3000);
    }


    private static class TrustAllCerts implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

        @Override
        public X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];}
    }

    private static class TrustAllHostnameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }

    private static SSLSocketFactory createSSLSocketFactory() {
        SSLSocketFactory ssfFactory = null;
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, new TrustManager[] { new TrustAllCerts() }, new SecureRandom());
            ssfFactory = sc.getSocketFactory();
        } catch (Exception e) {
        }

        return ssfFactory;
    }
}
